// Electron API Helper
// Provides a unified interface for IPC communication

const isElectron = () => {
  return window && window.require
}

const getIpcRenderer = () => {
  if (isElectron()) {
    const { ipcRenderer } = window.require('electron')
    return ipcRenderer
  }
  return null
}

export const electronAPI = {
  isElectron,
  
  invoke: async (channel, ...args) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      return await ipcRenderer.invoke(channel, ...args)
    }
    console.warn(`Electron API not available for channel: ${channel}`)
    return { error: true, message: 'Electron API not available' }
  },
  
  on: (channel, listener) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      ipcRenderer.on(channel, listener)
    }
  },
  
  once: (channel, listener) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      ipcRenderer.once(channel, listener)
    }
  },
  
  removeListener: (channel, listener) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      ipcRenderer.removeListener(channel, listener)
    }
  },
  
  removeAllListeners: (channel) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      ipcRenderer.removeAllListeners(channel)
    }
  },
  
  send: (channel, ...args) => {
    const ipcRenderer = getIpcRenderer()
    if (ipcRenderer) {
      ipcRenderer.send(channel, ...args)
    }
  }
}

// HTTP Client API
export const httpClient = {
  request: (config) => {
    try {
      // Create a serializable copy of the config
      const serializedConfig = JSON.parse(JSON.stringify(config))
      return electronAPI.invoke('module:http-client:request', serializedConfig)
    } catch (error) {
      console.error('Failed to serialize request config:', error)
      return Promise.reject(error)
    }
  }
}

// HTTP Server API
export const httpServer = {
  start: (config) => {
    try {
      const serializedConfig = JSON.parse(JSON.stringify(config))
      return electronAPI.invoke('module:http-server:start', serializedConfig)
    } catch (error) {
      console.error('Failed to serialize server config:', error)
      return Promise.reject(error)
    }
  },
  stop: () => electronAPI.invoke('module:http-server:stop'),
  addRoute: (route, handler) => {
    // Note: Functions cannot be passed through IPC, handler should be a string identifier
    return electronAPI.invoke('module:http-server:add-route', route, typeof handler === 'string' ? handler : handler.toString())
  },
  onRequestLog: (callback) => electronAPI.on('http-server:request-log', callback)
}

// MQTT API
export const mqtt = {
  connect: (config) => {
    try {
      const serializedConfig = JSON.parse(JSON.stringify(config))
      return electronAPI.invoke('module:mqtt:connect', serializedConfig)
    } catch (error) {
      console.error('Failed to serialize MQTT config:', error)
      return Promise.reject(error)
    }
  },
  subscribe: (topic, qos) => electronAPI.invoke('module:mqtt:subscribe', topic, qos),
  publish: (topic, message, qos, retain) => {
    try {
      // Ensure message is serializable
      const serializedMessage = typeof message === 'object' ? JSON.parse(JSON.stringify(message)) : message
      return electronAPI.invoke('module:mqtt:publish', topic, serializedMessage, qos, retain)
    } catch (error) {
      console.error('Failed to serialize MQTT message:', error)
      return Promise.reject(error)
    }
  },
  disconnect: () => electronAPI.invoke('module:mqtt:disconnect'),
  onConnected: (callback) => electronAPI.on('mqtt:connected', callback),
  onMessage: (callback) => electronAPI.on('mqtt:message', (event, data) => callback(data)),
  onError: (callback) => electronAPI.on('mqtt:error', (event, error) => callback(error)),
  onDisconnected: (callback) => electronAPI.on('mqtt:disconnected', callback)
}

// Dialog API
export const dialog = {
  openFile: (options) => {
    try {
      const serializedOptions = options ? JSON.parse(JSON.stringify(options)) : {}
      return electronAPI.invoke('dialog:open-file', serializedOptions)
    } catch (error) {
      console.error('Failed to serialize dialog options:', error)
      return Promise.reject(error)
    }
  },
  saveFile: (options) => {
    try {
      const serializedOptions = options ? JSON.parse(JSON.stringify(options)) : {}
      return electronAPI.invoke('dialog:save-file', serializedOptions)
    } catch (error) {
      console.error('Failed to serialize dialog options:', error)
      return Promise.reject(error)
    }
  }
}

// TCP/UDP API
export const tcpUdp = {
  // TCP Client
  tcpConnect: (config) => {
    try {
      const serializedConfig = JSON.parse(JSON.stringify(config))
      return electronAPI.invoke('tcp:connect', serializedConfig)
    } catch (error) {
      console.error('Failed to serialize TCP config:', error)
      return Promise.reject(error)
    }
  },
  tcpDisconnect: () => electronAPI.invoke('tcp:disconnect'),
  tcpSend: (options) => {
    try {
      const serializedOptions = JSON.parse(JSON.stringify(options))
      return electronAPI.invoke('tcp:send', serializedOptions)
    } catch (error) {
      console.error('Failed to serialize TCP send options:', error)
      return Promise.reject(error)
    }
  },
  
  // TCP Server
  tcpStartServer: (config) => {
    try {
      const serializedConfig = JSON.parse(JSON.stringify(config))
      return electronAPI.invoke('tcp:start-server', serializedConfig)
    } catch (error) {
      console.error('Failed to serialize TCP server config:', error)
      return Promise.reject(error)
    }
  },
  tcpStopServer: () => electronAPI.invoke('tcp:stop-server'),
  
  // UDP
  udpBind: (options) => {
    try {
      const serializedOptions = JSON.parse(JSON.stringify(options))
      return electronAPI.invoke('udp:bind', serializedOptions)
    } catch (error) {
      console.error('Failed to serialize UDP bind options:', error)
      return Promise.reject(error)
    }
  },
  udpSend: (options) => {
    try {
      const serializedOptions = JSON.parse(JSON.stringify(options))
      return electronAPI.invoke('udp:send', serializedOptions)
    } catch (error) {
      console.error('Failed to serialize UDP send options:', error)
      return Promise.reject(error)
    }
  },
  udpClose: (mode) => electronAPI.invoke('udp:close', mode),
  
  // Event listeners
  onTcpData: (callback) => electronAPI.on('tcp:data', (event, data) => callback(data)),
  onTcpError: (callback) => electronAPI.on('tcp:error', (event, error) => callback(error)),
  onTcpClientConnect: (callback) => electronAPI.on('tcp:client-connected', (event, client) => callback(client)),
  onTcpClientDisconnect: (callback) => electronAPI.on('tcp:client-disconnected', (event, clientId) => callback(clientId)),
  onTcpDisconnected: (callback) => electronAPI.on('tcp:disconnected', callback),
  onUdpData: (callback) => electronAPI.on('udp:data', (event, data) => callback(data)),
  onUdpError: (callback) => electronAPI.on('udp:error', (event, error) => callback(error))
}

// App API
export const app = {
  getVersion: () => electronAPI.invoke('app:get-version')
}

export default {
  electronAPI,
  httpClient,
  httpServer,
  mqtt,
  dialog,
  app,
  tcpUdp
}